/*
 * qe_spi.h
 *
 *  Created on: 2021/07/20
 *      Author: Wei.Studio
 */

#ifndef __QE_SPI_H__
#define __QE_SPI_H__



#include "qe_device.h"
#include "qe_bitops.h"



#define QE_SPI_BUS_SPI      QE_BIT(0)
#define QE_SPI_BUS_QSPI     QE_BIT(1)

#define QE_SPI_CPHA         QE_BIT(0)   /* clock phase */
#define QE_SPI_CPOL         QE_BIT(1)   /* clock polarity */
#define QE_SPI_MODE_0	    (0|0)	    /* (original MicroWire) */
#define QE_SPI_MODE_1	    (0|QE_SPI_CPHA)
#define QE_SPI_MODE_2	    (QE_SPI_CPOL|0)
#define QE_SPI_MODE_3	    (QE_SPI_CPOL|QE_SPI_CPHA)
#define QE_SPI_CS_HIGH	    QE_BIT(2)   /* CS active high */



typedef struct qe_spi_dev_message
{
    const void *send_buf;
    void *recv_buf;
    qe_size length;
    struct qe_spi_dev_message *next;

    unsigned cs_take    : 1;
    unsigned cs_release : 1;
	unsigned reserve    : 30;
}qe_spi_message;

typedef struct
{
    qe_u8 mode;
    qe_u8 data_width;
    qe_u16 reserved;

    qe_u32 max_hz;
}qe_spi_configure;

struct qe_spi_device;
struct qe_spi_dev_bus;

typedef struct
{
    qe_ret (*configure)(struct qe_spi_device *device, qe_spi_configure *cfg);
    qe_u32 (*xfer)(struct qe_spi_device *device, qe_spi_message *msg);
}qe_spi_ops;

typedef struct qe_spi_device
{
    qe_dev parent;
    struct qe_spi_dev_bus *bus;

    qe_spi_configure config;
    void   *user_data;
}qe_spi_dev;

typedef struct qe_spi_dev_bus
{
    qe_dev parent;
	
    qe_u32 mode 			:8;
	qe_u32 multi_access 	:1;
	qe_u32 reserve			:13;
	
    const qe_spi_ops *ops;

    qe_lock lock;

    qe_spi_dev *owner;
}qe_spi_bus;



qe_ret qe_spi_bus_attach_device(qe_spi_dev *spi, qe_const_str name,
	qe_const_str bus_name, qe_ptr user_data);

qe_ret qe_spidev_register(qe_spi_dev *spidev, qe_const_str name);

qe_ret qe_spi_bus_register(qe_spi_bus *bus, qe_const_str name,
	const qe_spi_ops *ops);

qe_int qe_spi_transfer(qe_spi_dev *dev, qe_const_ptr send_buf,
	qe_ptr recv_buf, qe_size length);

qe_int qe_spi_send_recv(qe_spi_dev *spi, 
	qe_const_ptr send_buf, qe_size send_length, 
	qe_ptr recv_buf, qe_size recv_length);

qe_spi_message *qe_spi_transfer_message(qe_spi_dev *dev, 
    qe_spi_message *message);

qe_ret qe_spi_bus_setlock(qe_spi_bus *bus, qe_ptr lock,
	qe_lock_acquire acquire,
	qe_lock_release release);

qe_int qe_spi_transfer_wait(qe_spi_dev *dev, qe_const_ptr send_buf,
	qe_ptr recv_buf, qe_size length, qe_uint wait);

qe_int qe_spi_send_recv_wait(qe_spi_dev *spi, 
	qe_const_ptr send_buf, qe_size send_length, 
	qe_ptr recv_buf, qe_size recv_length, qe_uint wait);

qe_spi_message *qe_spi_transfer_message_wait(qe_spi_dev *spi,
	qe_spi_message *message, qe_uint wait);



#endif /* __QE_SPI_H__ */

